package com.feinno.urcs.group.http.sub;

import com.feinno.sip.address.SipUri;
import com.feinno.sip.header.Expires;
import com.feinno.sip.header.ims.PAssertedIdentity;
import com.feinno.sip.header.ims.PAssertedIdentityHeader;
import com.feinno.sip.message.SipResponse;
import com.feinno.urcs.content.ResourceListArgs;
import com.feinno.urcs.content.ResourceLists;
import com.feinno.urcs.content.UrcsMultipartMimeContent;
import com.feinno.urcs.group.GroupConfiguration;
import com.feinno.urcs.group.GroupException;
import com.feinno.urcs.group.api.GroupService;
import com.feinno.urcs.group.api.GroupSubscriptionManager;
import com.feinno.urcs.group.entity.GroupIndex;
import com.feinno.urcs.group.entity.GroupInfo;
import com.feinno.urcs.group.entity.GroupMemberSubscription;
import com.feinno.urcs.group.entity.GroupSubscribeType;
import com.feinno.urcs.group.http.util.XcapParser;
import com.feinno.urcs.group.interop.entity.InteropGroupInviteArgs;
import com.feinno.urcs.group.pd.task.entity.PdBaseGroupNotifyArgs;
import com.feinno.urcs.group.pd.task.entity.PdGroupInfoNotifyArgs;
import com.feinno.urcs.group.siptask.task.GroupTaskEvents;
import com.feinno.urcs.nai.IMPU;
import com.feinno.urcs.sipservlet.SipServlet;
import com.feinno.urcs.sipservlet.SipServletException;
import com.feinno.urcs.sipservlet.SipServletRequest;
import com.feinno.urcs.types.MobileNo;
import com.feinno.util.Tuple2;
import org.helium.framework.annotations.ServiceSetter;
import org.helium.framework.annotations.TaskEvent;
import org.helium.framework.task.TaskProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sip.address.SipURI;
import javax.sip.address.TelURI;
import javax.sip.address.URI;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

/**
 * Created by wuzhiguo on 15-6-8.
 */
public class PdGroupSubscribeServlet extends SipServlet {

	private static final Logger LOGGER = LoggerFactory.getLogger(PdGroupSubscribeServlet.class);

	@ServiceSetter
	private GroupService groupService;
	@ServiceSetter
	private GroupSubscriptionManager subscriptionManager;
	@TaskEvent(GroupTaskEvents.GROUP_PD_INFO_NOTIFY)
	private TaskProducer<PdGroupInfoNotifyArgs> groupInfoNotifyTask;

	@Override
	protected void process(SipServletRequest request) throws SipServletException {
		try {
			if (LOGGER.isInfoEnabled()) {
				LOGGER.info(String.format("Received SipRequest: %s", request.toString()));
			}

			MobileNo fromMobileNo;
			List<Tuple2<Integer, String>> groups = new ArrayList<>();
			String groupFactoryUri;

			try {
				// todo 测试需要家PAI头
				URI fromUri = null;
				PAssertedIdentity paiHeader = (PAssertedIdentity) request.getHeader(PAssertedIdentity.NAME);
				if (paiHeader != null)
					fromUri = paiHeader.getAddress().getURI();
				fromMobileNo = MobileNo.parseFrom(getMobileNo(fromUri));
				groupFactoryUri = request.getRequestURI().toString();
				if (!groupFactoryUri.equals(GroupConfiguration.INSTANCE.getRcseConferenceUri())) {
					LOGGER.error("check RequestUri error : " + groupFactoryUri);
					request.sendResponse(400);
					return;
				}
				// Paser Body
				UrcsMultipartMimeContent contents = request.getMultipartMimeContent();
				if (contents != null) {
					ResourceLists resourceList = contents.getContent(ResourceLists.class);
					for (ResourceListArgs.Entry entry : resourceList.getResourceListArgs().getEntryList()) {
						XcapParser parser = new XcapParser();
						parser.parse(entry.getUri());
						String groupUri = parser.getXui();
						groupService.check(fromMobileNo, groupUri);
						Tuple2<Integer, String> combo2 = new Tuple2<>(getGroupIdFromUri(groupUri), groupUri);
						groups.add(combo2);
					}
				}
			} catch (GroupException e) {
				LOGGER.error(String.format("check params GroupException. Received SipRequest: %s", request.toString()), e);
				SipResponse response = request.createResponse(e.getError().getSipCode());
				request.sendResponse(response);
				return;
			} catch (ParseException e) {
				LOGGER.error(String.format("check params ParseException. Received SipRequest: %s", request.toString()), e);
				request.sendResponse(400);
				return;
			} catch (Exception e) {
				LOGGER.error(String.format("check params Exception. Received SipRequest: %s", request.toString()), e);
				request.sendResponse(500);
				return;
			}

			SipResponse response = request.createResponse(200);
			Expires expires = new Expires();
			expires.setExpires(GroupConfiguration.INSTANCE.getSubscriptionExpires());
			response.setHeader(expires);
			request.sendResponse(response);

			for (Tuple2 group : groups) {
				// 保存订阅信息
				int groupId = (int)group.getV1();
				String groupUri = (String)group.getV2();
				GroupMemberSubscription subscription = new GroupMemberSubscription();
				subscription.setUserMobile(fromMobileNo);
				String callId = request.getCallIdHeader().getCallId();
				subscription.setCallId(callId);
				subscription.setCSeq((int) request.getCseq().getSeqNumber() + 1);
				subscription.setFromTag(response.getToHeader().getTag());
				subscription.setToTag(request.getFromHeader().getTag());
				subscription.setExpires(3600);
				subscription.setSubType(GroupSubscribeType.PD_GROUP);
				subscriptionManager.subscribeConference(groupId, fromMobileNo, subscription);
				// 下全量通知
				GroupIndex index = groupService.getGroupIndex(groupId);
				GroupInfo groupInfo = groupService.getGroupInfo(index);
				PdBaseGroupNotifyArgs baseGroupNotify = new PdBaseGroupNotifyArgs();
				PAssertedIdentityHeader pai = (PAssertedIdentityHeader) request.getHeader(PAssertedIdentityHeader.NAME);
				baseGroupNotify.setRequestUri(pai.getAddress().getURI().toString());
				baseGroupNotify.setFromUri(request.getTo().getAddress().getURI().toString());
				baseGroupNotify.setToUri(request.getFrom().getAddress().getURI().toString());
				baseGroupNotify.setFromTag(response.getTo().getTag());
				baseGroupNotify.setToTag(request.getFrom().getTag());
				baseGroupNotify.setCallId(request.getCallIdHeader().getCallId());
				baseGroupNotify.setCseq((int) (request.getCseq().getSeqNumber() + 1));
				baseGroupNotify.setExpired(GroupConfiguration.INSTANCE.getSubscriptionExpires());
				baseGroupNotify.setGroupUri(groupUri);
				baseGroupNotify.setPreviousEtag("");
				baseGroupNotify.setNewEtag(String.valueOf(groupInfo.getAttributesVersion()));
				PdGroupInfoNotifyArgs args = new PdGroupInfoNotifyArgs();
				args.setBaseGroupNotify(baseGroupNotify);
				args.setGroupInfo(groupInfo);
				groupInfoNotifyTask.produce(args);
			}
		} catch (Exception ex) {
			LOGGER.error(String.format("process() Error. Received SipRequest: %s", request.toString()), ex);
		}
	}


	protected String getMobileNo(URI uri) {
		if (uri == null) {
			return null;
		} else if (uri.isSipURI()) {
			return ((SipUri) uri).getUser();
		} else {
			return "+" + ((TelURI) uri).getPhoneNumber();
		}
	}

	protected int getGroupIdFromUri(String groupUri) {
		URI uri = IMPU.parse(groupUri).toUri();
		if (uri.isSipURI()) {
			String gId = ((SipURI) uri).getUser().toString();
			return Integer.parseInt(gId.substring(GroupConfiguration.INSTANCE.getGroupPrefix().length()));
		} else {
			return 0;
		}
	}
}
